'require view';
'require fs';
'require ui';
+'require uci';
/*
button handling
]);
document.getElementById('refresh').focus();
}
+
+ if (ev === 'map') {
+ let md = L.ui.showModal(null, [
+ E('div', { id: 'mapModal',
+ style: 'position: relative;' }, [
+ E('iframe', {
+ id: 'mapFrame',
+ src: L.resource('view/adblock/map.html'),
+ style: 'width: 100%; height: 80vh; border: none;'
+ }),
+ ]),
+ E('div', { 'class': 'right' }, [
+ E('button', {
+ 'class': 'btn cbi-button',
+ 'click': ui.createHandlerFn(this, function (ev) {
+ ui.hideModal();
+ sessionStorage.clear();
+ location.reload();
+ })
+ }, _('Cancel')),
+ ' ',
+ E('button', {
+ 'class': 'btn cbi-button-action',
+ 'click': ui.createHandlerFn(this, function (ev) {
+ const iframe = document.getElementById('mapFrame');
+ iframe.contentWindow.location.reload();
+ })
+ }, _('Map Reset'))
+ ])
+ ]);
+ md.style.maxWidth = '90%';
+ document.getElementById('mapModal').focus();
+ }
}
return view.extend({
load: function() {
- return L.resolveDefault(fs.exec_direct('/etc/init.d/adblock', ['report', 'json', '10', '50', '+']),'');
+ return Promise.all([
+ L.resolveDefault(fs.exec_direct('/etc/init.d/adblock', ['report', 'json', '10', '50', '+']),''),
+ uci.load('adblock')
+ ]);
},
render: function(dnsreport) {
- if (!dnsreport) {
- dnsreport = '{}';
- };
- var content;
- content = JSON.parse(dnsreport);
+ let content, notMsg, errMsg;
+
+ if (dnsreport) {
+ try {
+ content = JSON.parse(dnsreport[0]);
+ } catch (e) {
+ content = "";
+ if (!errMsg) {
+ errMsg = true;
+ ui.addNotification(null, E('p', _('Unable to parse the report file!')), 'error');
+ }
+ }
+ } else {
+ content = "";
+ }
var rows_top = [];
var tbl_top = E('table', { 'class': 'table', 'id': 'top_10' }, [
]);
var max = 0;
- if (content.top_clients && content.top_domains && content.top_blocked) {
- max = Math.max(content.top_clients.length, content.top_domains.length, content.top_blocked.length);
+ if (content[0].top_clients && content[0].top_domains && content[0].top_blocked) {
+ max = Math.max(content[0].top_clients.length, content[0].top_domains.length, content[0].top_blocked.length);
}
for (var i = 0; i < max; i++) {
var a_cnt = '\xa0', a_addr = '\xa0', b_cnt = '\xa0', b_addr = '\xa0', c_cnt = '\xa0', c_addr = '\xa0';
- if (content.top_clients[i]) {
- a_cnt = content.top_clients[i].count;
+ if (content[0].top_clients[i]) {
+ a_cnt = content[0].top_clients[i].count;
}
- if (content.top_clients[i]) {
- a_addr = content.top_clients[i].address;
+ if (content[0].top_clients[i]) {
+ a_addr = content[0].top_clients[i].address;
}
- if (content.top_domains[i]) {
- b_cnt = content.top_domains[i].count;
+ if (content[0].top_domains[i]) {
+ b_cnt = content[0].top_domains[i].count;
}
- if (content.top_domains[i]) {
- b_addr = '<a href="https://duckduckgo.com/?q=' + encodeURIComponent(content.top_domains[i].address) + '&k1=-1&km=l&kh=1" target="_blank" rel="noreferrer noopener" title="Domain Lookup">' + content.top_domains[i].address + '</a>';
+ if (content[0].top_domains[i]) {
+ b_addr = '<a href="https://ip-api.com/#' + encodeURIComponent(content[0].top_domains[i].address) + '" target="_blank" rel="noreferrer noopener" title="Domain Lookup">' + content[0].top_domains[i].address + '</a>';
}
- if (content.top_blocked[i]) {
- c_cnt = content.top_blocked[i].count;
+ if (content[0].top_blocked[i]) {
+ c_cnt = content[0].top_blocked[i].count;
}
- if (content.top_blocked[i]) {
- c_addr = '<a href="https://duckduckgo.com/?q=' + encodeURIComponent(content.top_blocked[i].address) + '&k1=-1&km=l&kh=1" target="_blank" rel="noreferrer noopener" title="Domain Lookup">' + content.top_blocked[i].address + '</a>';
+ if (content[0].top_blocked[i]) {
+ c_addr = '<a href="https://ip-api.com/#' + encodeURIComponent(content[0].top_blocked[i].address) + '" target="_blank" rel="noreferrer noopener" title="Domain Lookup">' + content[0].top_blocked[i].address + '</a>';
}
rows_top.push([
a_cnt,
]);
max = 0;
- if (content.requests) {
+ if (content[0].requests) {
var button;
- max = content.requests.length;
+ max = content[0].requests.length;
for (var i = 0; i < max; i++) {
- if (content.requests[i].rc === 'NX') {
+ if (content[0].requests[i].rc === 'NX') {
button = E('button', {
'class': 'btn cbi-button cbi-button-positive',
'style': 'word-break: inherit',
'name': 'allowlist',
- 'value': content.requests[i].domain,
+ 'value': content[0].requests[i].domain,
'click': handleAction
}, [ _('Allowlist...') ]);
} else {
'class': 'btn cbi-button cbi-button-negative',
'style': 'word-break: inherit',
'name': 'blocklist',
- 'value': content.requests[i].domain,
+ 'value': content[0].requests[i].domain,
'click': handleAction
}, [ _('Blocklist...') ]);
}
rows_requests.push([
- content.requests[i].date,
- content.requests[i].time,
- content.requests[i].client,
- '<a href="https://duckduckgo.com/?q=' + encodeURIComponent(content.requests[i].domain) + '&k1=-1&km=l&kh=1" target="_blank" rel="noreferrer noopener" title="Domain Lookup">' + content.requests[i].domain + '</a>',
- content.requests[i].rc,
+ content[0].requests[i].date,
+ content[0].requests[i].time,
+ content[0].requests[i].client,
+ '<a href="https://ip-api.com/#' + encodeURIComponent(content[0].requests[i].domain) + '" target="_blank" rel="noreferrer noopener" title="Domain Lookup">' + content[0].requests[i].domain + '</a>',
+ content[0].requests[i].rc,
button
]);
}
E('p', '\xa0'),
E('div', { 'class': 'cbi-value' }, [
E('div', { 'class': 'cbi-value-title', 'style': 'float:left;width:230px' }, _('Start Timestamp')),
- E('div', { 'class': 'cbi-value-title', 'id': 'start', 'style': 'float:left;color:#37c' }, (content.start_date || '-') + ', ' + (content.start_time || '-'))
+ E('div', { 'class': 'cbi-value-title', 'id': 'start', 'style': 'float:left;color:#37c' }, (content[0].start_date || '-') + ', ' + (content[0].start_time || '-'))
]),
E('div', { 'class': 'cbi-value' }, [
E('div', { 'class': 'cbi-value-title', 'style': 'float:left;width:230px' }, _('End Timestamp')),
- E('div', { 'class': 'cbi-value-title', 'id': 'end', 'style': 'float:left;color:#37c' }, (content.end_date || '-') + ', ' + (content.end_time || '-'))
+ E('div', { 'class': 'cbi-value-title', 'id': 'end', 'style': 'float:left;color:#37c' }, (content[0].end_date || '-') + ', ' + (content[0].end_time || '-'))
]),
E('div', { 'class': 'cbi-value' }, [
E('div', { 'class': 'cbi-value-title', 'style': 'float:left;width:230px' }, _('Total DNS Requests')),
- E('div', { 'class': 'cbi-value-title', 'id': 'total', 'style': 'float:left;color:#37c' }, content.total || '-')
+ E('div', { 'class': 'cbi-value-title', 'id': 'total', 'style': 'float:left;color:#37c' }, content[0].total || '-')
]),
E('div', { 'class': 'cbi-value' }, [
E('div', { 'class': 'cbi-value-title', 'style': 'float:left;width:230px' }, _('Blocked DNS Requests')),
- E('div', { 'class': 'cbi-value-title', 'id': 'blocked', 'style': 'float:left;color:#37c' }, (content.blocked || '-') + ' (' + (content.percent || '-') + ')')
+ E('div', { 'class': 'cbi-value-title', 'id': 'blocked', 'style': 'float:left;color:#37c' }, (content[0].blocked || '-') + ' (' + (content[0].percent || '-') + ')')
])
]),
E('div', { 'class': 'cbi-section' }, [
])
]),
E('div', { 'class': 'cbi-page-actions' }, [
+ E('button', {
+ 'class': 'btn cbi-button cbi-button-apply',
+ 'style': 'float:none;margin-right:.4em;',
+ 'click': ui.createHandlerFn(this, function () {
+ if (uci.get('adblock', 'global', 'adb_map') !== '1') {
+ if (!notMsg) {
+ notMsg = true;
+ return ui.addNotification(null, E('p', _('GeoIP Map is not enabled!')), 'info');
+ }
+ }
+ if (content[1] && content[1].length > 1) {
+ sessionStorage.setItem('mapData', JSON.stringify(content[1]));
+ return handleAction('map');
+ }
+ else {
+ if (!notMsg) {
+ notMsg = true;
+ return ui.addNotification(null, E('p', _('No GeoIP Map data!')), 'info');
+ }
+ }
+ })
+ }, [_('Map...')]),
E('button', {
'class': 'btn cbi-button cbi-button-apply',
'style': 'float:none;margin-right:.4em;',
--- /dev/null
+<!DOCTYPE html>
+<html>
+
+<head>
+ <title>adblock Map</title>
+ <meta charset="utf-8" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+
+ integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY=" crossorigin="" />
+ <style>
+ #map {
+ height: 97vh;
+ width: 100%;
+ }
+
+ .mono {
+ font-size: small;
+ font-family: monospace;
+ white-space: nowrap;
+ margin: 0.3em !important;
+ }
+ </style>
+</head>
+
+<body>
+ <div id="map"></div>
+
+ integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=" crossorigin=""></script>
+ <script>
+ 'use strict';
+
+ /* get mapData */
+ const mapData = sessionStorage.getItem('mapData');
+ if (mapData) {
+ let uniqueCoordinates = [];
+ let homeCoordinates = [];
+ const parsedData = JSON.parse(mapData);
+ parsedData.forEach(function (item, index) {
+ if (Object.keys(item).length !== 0) {
+ let keys = Object.keys(item);
+ keys.forEach(function (key) {
+ if (item[key] && item[key].lat && item[key].lon && item[key].query && item[key].as && item[key].city && item[key].countryCode) {
+ let coordObj = { lat: item[key].lat, lon: item[key].lon };
+ if (key === "homeIP" && !homeCoordinates.some(existingCoord => existingCoord.lat === coordObj.lat && existingCoord.lon === coordObj.lon)) {
+ coordObj = { key: key, lat: item[key].lat, lon: item[key].lon, query: item[key].query, as: item[key].as, city: item[key].city, cc: item[key].countryCode };
+ homeCoordinates.push(coordObj);
+ }
+ if (key !== "homeIP" && !uniqueCoordinates.some(existingCoord => existingCoord.lat === coordObj.lat && existingCoord.lon === coordObj.lon)) {
+ coordObj = { key: key, lat: item[key].lat, lon: item[key].lon, query: item[key].query, as: item[key].as, city: item[key].city, cc: item[key].countryCode };
+ uniqueCoordinates.push(coordObj);
+ }
+ }
+ });
+ }
+ });
+
+ /* intialize map and map tiles */
+ let map;
+ homeCoordinates.forEach(function (coordObj) {
+ let latHome = coordObj.lat;
+ let lonHome = coordObj.lon;
+ let ipHome = coordObj.query.slice(0, 38);
+ let asHome = coordObj.as.slice(0, 38);
+ let cityHome = coordObj.city.slice(0, 33);
+ let ccHome = coordObj.cc;
+
+ if (typeof map === "undefined") {
+ map = L.map('map', {
+ zoom: 6,
+ minZoom: 2,
+ maxZoom: 18,
+ center: [latHome, lonHome]
+ }).setView([latHome, lonHome]);
+ L.tileLayer('https://{s}.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}.png', {
+ attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
+ }).addTo(map);
+ }
+
+ /* render markers for local IPs */
+ let circle = L.circleMarker([latHome, lonHome]).addTo(map);
+ circle.setStyle({ color: '#378242', opacity: 1.0, fillColor: '#378242', fillOpacity: 0.5, radius: 6 });
+ circle.bindPopup("<b><center>local IP</center></b>" +
+ "<p class=\"mono\">" +
+ "City: " + cityHome + " (" + ccHome + ")" +
+ "<br />Latitude : " + latHome +
+ "<br />Longitude: " + lonHome +
+ "<br />IP: " + ipHome +
+ "<br />AS: " + asHome +
+ "</p>");
+ });
+
+ /* render markers for blocked Domains */
+ uniqueCoordinates.forEach(function (coordObj) {
+ let key = coordObj.key;
+ let lat = coordObj.lat;
+ let lon = coordObj.lon;
+ let ip = coordObj.query.slice(0, 38);
+ let as = coordObj.as.slice(0, 38);
+ let city = coordObj.city.slice(0, 33);
+ let cc = coordObj.cc;
+ let circle = L.circleMarker([lat, lon]).addTo(map);
+ circle.setStyle({ color: '#C22121', opacity: 1.0, fillColor: '#C22121', fillOpacity: 0.5, radius: 2 });
+ circle.bindPopup("<b><center>" + key + "</center></b>" +
+ "<p class=\"mono\">" +
+ "City: " + city + " (" + cc + ")" +
+ "<br />Latitude : " + lat +
+ "<br />Longitude: " + lon +
+ "<br />IP: " + ip +
+ "<br />AS: " + as +
+ "</p>");
+ });
+ }
+ </script>
+</body>
+
+</html>
\ No newline at end of file
if (backend && info) {
backend.textContent = info.dns_backend || '-';
}
- var utils = document.getElementById('utils');
- if (utils && info) {
- utils.textContent = info.run_utils || '-';
- }
var ifaces = document.getElementById('ifaces');
if (ifaces && info) {
ifaces.textContent = info.run_ifaces || '-';
E('label', { 'class': 'cbi-value-title', 'style': 'margin-bottom:-5px;padding-top:0rem;' }, _('DNS Backend')),
E('div', { 'class': 'cbi-value-field', 'id': 'backend', 'style': 'margin-bottom:-5px;color:#37c;' }, '-')
]),
- E('div', { 'class': 'cbi-value' }, [
- E('label', { 'class': 'cbi-value-title', 'style': 'margin-bottom:-5px;padding-top:0rem;' }, _('Run Utils')),
- E('div', { 'class': 'cbi-value-field', 'id': 'utils', 'style': 'margin-bottom:-5px;color:#37c;' }, '-')
- ]),
E('div', { 'class': 'cbi-value' }, [
E('label', { 'class': 'cbi-value-title', 'style': 'margin-bottom:-5px;padding-top:0rem;' }, _('Run Interfaces')),
E('div', { 'class': 'cbi-value-field', 'id': 'ifaces', 'style': 'margin-bottom:-5px;color:#37c;' }, '-')
o = s.taboption('additional', form.Flag, 'adb_debug', _('Verbose Debug Logging'), _('Enable verbose debug logging in case of any processing errors.'));
o.rmempty = false;
- o = s.taboption('additional', form.Flag, 'adb_nice', _('Low Priority Service'), _('Reduce the priority of the adblock background processing to take fewer resources from the system.'));
- o.enabled = '10';
+ o = s.taboption('additional', form.ListValue, 'adb_nicelimit', _('Nice Level'), _('The selected priority will be used for adblock background processing.'));
+ o.value('-20', _('Highest Priority'));
+ o.value('-10', _('High Priority'));
+ o.value('0', _('Normal Priority'));
+ o.value('10', _('Less Priority'));
+ o.value('19', _('Least Priority'));
+ o.default = '0';
+ o.placeholder = _('-- default --');
+ o.create = true;
+ o.optional = true;
o.rmempty = true;
- o = s.taboption('additional', form.Value, 'adb_tmpbase', _('Base Temp Directory'), _('Base temp directory for all adblock related runtime operations, \
- e.g. downloading, sorting, merging etc.'));
+ o = s.taboption('additional', form.Value, 'adb_basedir', _('Base Directory'), _('Base working directory during adblock processing.'));
o.placeholder = '/tmp';
o.rmempty = true;
o = s.taboption('adv_report', form.Flag, 'adb_represolve', _('Resolve IPs'), _('Resolve reporting IP addresses by using reverse DNS (PTR) lookups.'));
o.rmempty = true;
+ o = s.taboption('adv_report', form.Flag, 'adb_map', _('GeoIP Map'), _('Enable a GeoIP map that shows the geographical location of the blocked domains. This requires external requests to get the map tiles and geolocation data.'));
+ o.optional = true;
+ o.rmempty = true;
+
/*
advanced email settings tab
*/